//
// Created by LiuYou on 2021/8/4.
//

#include <cstdio>
#include <cstdlib>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iostream>
#include "Proto.hpp"


#define IP_STR_SIZE             40


int main() {
    int socketFD = socket( PF_INET, SOCK_DGRAM, 0 );
    if (socketFD < 0) {
        perror( "socket()" );
        exit( 1 );
    }


    struct sockaddr_in localAddress{
            // sin_ : socket internet
            .sin_family=AF_INET,
            .sin_port=htons( atoi( RCV_PORT )),
    };
    inet_pton( AF_INET, "0.0.0.0", &localAddress.sin_addr );


    // 对 &localAddress不能通过static_cast进行强转, 必须使用C式的强转。
    int ret = bind( socketFD, (sockaddr*) (&localAddress), sizeof( localAddress ));
    if (ret < 0) {
        perror( "bind()" );
        exit( 1 );
    }

    using SocketBasic::Msg;
    Msg* rcvMsg;
    size_t msgSize = sizeof( Msg ) + NAME_MAX - 1;
    void* pVoid = malloc( msgSize );
    rcvMsg = static_cast<Msg*>(pVoid);
    if (rcvMsg == nullptr) {
        perror( "malloc()" );
        exit( 1 );
    }
    struct sockaddr_in remoteAddress{};
    /* !!! */
    socklen_t remoteAddressLen = sizeof( remoteAddress );
    while (true) {
        recvfrom( socketFD, rcvMsg, msgSize, 0,
                  (sockaddr*) (&remoteAddress), &remoteAddressLen );
        char ipStr[IP_STR_SIZE];
        inet_ntop( AF_INET, &remoteAddress.sin_addr, ipStr, IP_STR_SIZE );
        fprintf( stdout, "=====message from %s:%d=====\n",
                 ipStr,
                 ntohs( remoteAddress.sin_port ));
        std::cout << *rcvMsg << std::endl;
    }

    close( socketFD );

    exit( 0 );
}